home *** CD-ROM | disk | FTP | other *** search
- /*
- "Floating.c"
-
- This file offers substitute routines for commonly used calls to the
- window manager in order to gain the advantage of supporting multiple
- floating windows (such as an info window, a tool pallete, etc.)
- */
-
- /*
- Change History
- (while in the hands of John DeWeese)
-
- 8/30/95 -
- Altered DragTheWindow to more closely emulate the standard DragWindow(),
- added an if (StillDown()) after SelectTheWindow() to give it a time
- cushioned effect.
-
- 11/14/95 -
- Commented out the ReactToRemoval() in the function HideTheWindow()
- because of a display bug it cause on my PowerMac with System 7.5.
- Since this bug was tested on other systems as well, I believe this
- has cured it. If windows are not hiliting at all once one is closed,
- this procedure may be suspect. Thus, it is simply commented.
-
- 11/20/95 -
- Removed the superfluous PaintOne() and CalcVis() from SelectTheWindow().
- PaintOne() was the cause of a mysterious flicker upon update of the
- window, and CalcVis() seems to be docile, but uneccessary.
- */
-
- #include "Floating.h"
-
- // global variables
- WindowPtr bottomFloat;
- WindowPtr topFloat;
- WindowPtr topWindow;
-
- /*
- ActivateWindow hilites/unhilites the window and then generates an
- activate/deactivate event for it. In order to generate activate
- events, it mucks with low-mem globals. It would be cleaner to
- directly call the activate routine for the window. The advantage
- of this method is that it also works with modeless dialogs.
- The Dialog Manager doesn't know that a dialog is active unless
- it actually receives an activate event.
- */
-
- void ActivateWindow (WindowPtr window, Boolean on)
- {
- WindowPtr *p;
-
- if (window != nil)
- {
- HiliteWindow(window, on);
- if (on)
- p = (WindowPtr *)(CurActivate);
- else
- p = (WindowPtr *)(CurDeactive);
- p = &window;
- }
- }
-
- /*
- InitFloats is to be called at the beginning of the program,
- before creating any windows. It sets our global variables to nil.
- */
-
- void InitFloats (void)
- {
- topFloat = nil;
- bottomFloat = nil;
- topWindow = nil;
- }
-
- /*
- IsFloating and IsVisible are little, foolproof routines that tell
- whether a window is floating or visible. Using them avoids errors
- such as examining WindowPeek(whichWindow)->visible when whichWindow == nil
- */
-
- Boolean IsFloating (WindowPtr whichWindow)
- {
- if (whichWindow == nil)
- return false;
- else
- return (((WindowPeek)whichWindow)->windowKind == kFloatingKind);
- }
-
- Boolean IsVisible (WindowPtr whichWindow)
- {
- if (whichWindow == nil)
- return false;
- else
- return (((WindowPeek)whichWindow)->visible);
- }
-
- /*
- UpdateFloats updates the topFloat and bottomFloat variables by walking
- down the window list. It then determines topWindow by taking the first
- visible window after bottomFloat.
- */
-
- void UpdateFloats (void)
- {
- WindowPtr theWindow = FrontWindow();
-
- if (IsFloating(theWindow))
- {
- topFloat = theWindow;
- while ((theWindow != nil) && (IsFloating(theWindow)))
- {
- bottomFloat = theWindow;
- theWindow = (WindowPtr)(((WindowPeek)theWindow)->nextWindow);
- }
-
- while ((theWindow != nil) && (!IsVisible(theWindow)))
- theWindow = (WindowPtr)(((WindowPeek)theWindow)->nextWindow);
- topWindow = theWindow;
- }
- else
- {
- topFloat = nil;
- bottomFloat = nil;
- topWindow = FrontWindow();
- }
- }
-
- /*
- MakeFloat turns a newly created window into a floating window and
- brings it to the front. The window must have been created via a call
- to [Get]NewWindow().
- */
-
- void MakeFloat (WindowPtr theWindow)
- {
- BringToFront(theWindow);
- ShowHide(theWindow, true);
- if (topFloat == nil)
- bottomFloat = theWindow;
- topFloat = theWindow;
- ((WindowPeek)theWindow)->windowKind = kFloatingKind;
- }
-
- /*
- ReactToRemoval handles a few necessary steps after killing whichWindow.
- underWindow is the window that was under whichWindow
- (i.e. next to it in the window list).
- */
-
- void ReactToRemoval (WindowPeek underWindow)
- {
- while ((underWindow != nil) && (!IsVisible((WindowPtr)underWindow)))
- {
- underWindow = underWindow->nextWindow;
- }
- ActivateWindow((WindowPtr)underWindow, true);
- UpdateFloats();
- }
-
- void HideTheWindow (WindowPtr whichWindow)
- {
- WindowPeek underWindow;
-
- underWindow = ((WindowPeek)whichWindow)->nextWindow;
- HideWindow(whichWindow);
- //ReactToRemoval(underWindow);
- }
-
- void DisposeTheWindow (WindowPtr whichWindow)
- {
- WindowPeek underWindow;
-
- underWindow = ((WindowPeek)whichWindow)->nextWindow;
- DisposeWindow(whichWindow);
- ReactToRemoval(underWindow);
- }
-
- /*
- SelectTheWindow is the most important routine. Here's what we do:
- If whichWindow is not visible, show it.
- - If whichWindow is a floating window, just bring it to the front.
- - If it is a regular window and there are no floating windows, bring
- it to the front, activate it, deactivate the former front window.
- - If it is a regular window and there are floating windows, send it
- behind bottomFloat, activate it, deactivate the old topWindow
- Finally, update the global float variables.
- */
-
- void SelectTheWindow (WindowPtr whichWindow)
- {
- if (!(((WindowPeek)whichWindow)->visible))
- ShowHide(whichWindow, true);
-
- if (IsFloating(whichWindow))
- {
- BringToFront(whichWindow);
- HiliteWindow(whichWindow, true);
- }
- else
- {
- if (whichWindow != topWindow)
- {
- if (bottomFloat != nil)
- {
- SendBehind(whichWindow, bottomFloat);
- //PaintOne(whichWindow, ((WindowPeek)whichWindow)->strucRgn);
- //CalcVis(whichWindow);
- }
- else
- BringToFront(whichWindow);
-
- ActivateWindow(whichWindow, true);
- ActivateWindow(topWindow, false);
- }
- }
-
- UpdateFloats();
- }
-
- /*
- DragTheWindow is to be called instead of DragWindow, because DragWindow
- brings the window to the front unless the command key is down. We use
- DragGrayRgn to drag a gray outline of the window. We clip the dragging
- to a region consisting of the whole desktop minus the windows that are
- in front of the window we're dragging. To emulate DragWindow's behavior,
- we send the window to the front, unless the command key is down.
- */
-
- void DragTheWindow (WindowPtr whichWindow, EventRecord *Event)
- {
- GrafPtr savePort;
- GrafPort wPort;
- Point thePoint;
- long newLoc;
- WindowPeek theWindow;
- Rect dragRect;
- RgnHandle dragRgn;
-
- if (!(Event->modifiers & cmdKey))
- SelectTheWindow(whichWindow);
-
- if (StillDown())
- {
- GetPort(&savePort);
- SetPort(whichWindow);
- thePoint.h = whichWindow->portRect.left;
- thePoint.v = whichWindow->portRect.top;
- LocalToGlobal(&thePoint);
- dragRgn = NewRgn();
- CopyRgn(((WindowPeek)whichWindow)->strucRgn, dragRgn);
-
- OpenPort(&wPort);
- CopyRgn(GetGrayRgn(), wPort.visRgn);
- theWindow = (WindowPeek)(FrontWindow());
- while (theWindow != ((WindowPeek)whichWindow))
- {
- DiffRgn(wPort.visRgn, theWindow->strucRgn, wPort.visRgn);
- theWindow = theWindow->nextWindow;
- }
-
- dragRect = (*GetGrayRgn())->rgnBBox;
- InsetRect(&dragRect, 4, 4);
-
- // Here is the heart of the drag action. nil at the end is a space for a DragGrayRgnUPP
- newLoc = DragGrayRgn(dragRgn, Event->where, &dragRect, &dragRect, noConstraint, nil);
- if ((newLoc != cancelDrag) && (newLoc != 0))
- MoveWindow(whichWindow, thePoint.h + LoWord(newLoc),
- thePoint.v + HiWord(newLoc), false);
-
- DisposeRgn(dragRgn);
- ClosePort(&wPort);
- SetPort(savePort);
- }
- else
- {
- SelectTheWindow(whichWindow);
- }
- }
-
- /*
- HideFloats/ShowFloats are simple routines that hide/show all floating
- windows. They're useful to handle suspend/resume events.
-
- */
-
- void HideFloats (void)
- {
- while (IsFloating(FrontWindow()))
- HideWindow(FrontWindow());
- //topFloat = nil;
- //bottomFloat = nil;
- }
-
- /*
- **************** Note ****************
- ShowFloats is buggy.
-
- After calling ShowFloats, the window
- behind the topWindow is lost track of.
- Put another way, topWindow's
- "nextWindow" is updated incorrectly.
- That means that even if new windows
- are created, that link is still lost.
- **************************************
- */
-
- void ShowFloats (void)
- {
- WindowPtr
- theWindow,
- *p;
-
- p = (WindowPtr *)(WindowList);
- theWindow = (*p);
- while (theWindow != nil)
- {
- if (IsFloating(theWindow))
- {
- ShowHide(theWindow, true);
- HiliteWindow(theWindow, true);
- }
- theWindow = (WindowPtr)((WindowPeek)theWindow)->nextWindow;
- }
- }